#include "ServerSocket.hpp"

/*
To be able to use Thread/pthread Class we have to build C like function to pass to
the Thread->Start(...) function.

Here is the list of helper function used in the ServerSocket Class.
*/

#define DEFAULT_BUFFLEN 512


ServerSocket::ServerSocket(void)
{
	//socket = new Socket();
	nbClients = 0;
}


ServerSocket::~ServerSocket(void)
{
	//kill all clients in the vector ???
	
	
	/*
	for(int i = 0; i < (int)clients.size(); i++)
	{
		//KillClient(
	}
	*/

	//removes clients in the vector
	clients.clear();
}


/*
ILLIMITED_CONNETIONS is a value telling that the server always accept incomming connection

This function is blocking for waiting connections
SHOULD be use with a job...Thread(ThreadJob)
This code is an infite loop of accepting socket

- If a Job is pass, when a connexion is establish the job will be launch.
- If no job the SOCKET handle is returned
- The job must delete data from the vector
*/
SOCKET ServerSocket::WaitForConnection(int port, int nbConnections = ILLIMITED_CONNETIONS, ThreadJob * Job = NULL)
{
	server = socket.CreateSocket(); //default stream
	
	struct sockaddr_in sin;

	sin.sin_family = AF_INET;
	sin.sin_addr.s_addr = INADDR_ANY;
	sin.sin_port = htons( port );

	if(socket.Bind(server,(sockaddr *)&sin, sizeof sin ) == -1)
	{
		int err = WSAGetLastError();
		return err;
	}

	while(socket.Listen(server,nbConnections) == -1);

	SOCKET client;	
	struct sockaddr_in their_addr;
	int len = sizeof(their_addr);
	
	while(1)
	{		
		Thread t;

		client = socket.Accept(server,(struct sockaddr *)&their_addr,&len);
		this->AddClientToVector(client);

		if(client == INVALID_SOCKET)
		{
			int err = WSAGetLastError();
			socket.Close(client);
			return err;
		}	
		else
		{
			nbClients++;
			printf("Connection establish from: %s\n", inet_ntoa(their_addr.sin_addr));			
		}

		//launch a job if one exist
		if(Job != NULL)
		{			
			t.Start(Job);
			//t->Join(); We never wait the end of the Thread we continue waiting for more connections
			return client; //thread is running in background and we return the client SOCKET 
		}
		//No job
		else
		{
			//return client; //this loop need to be infinite so no return, except for debug
			this->AddClientToVector(client);
			return client;
		}
	}

	//some kind of weird error...
	return 0;
}

/*
This function is an LayerOver Socket Class. No loop is done here
*/
char * ServerSocket::ReceiveData(SOCKET s)
{
	char * buf = "";//[DEFAULT_BUFFLEN];
	//memset(buf,0,sizeof(buf));

	int nbData = socket.Receive(s,buf,DEFAULT_BUFFLEN,0);
	if(nbData == 0)
	{
		printf("Connection lost");
		return 0;
	}
	else if(nbData < 0)
	{
		int err = WSAGetLastError();
		printf("Socket Error: %d", err);
	}
	return buf;
}

/*
Send data to the socket
*/
int ServerSocket::SendData(SOCKET s, char * data)
{
	return socket.Send(s, data,(int)strlen(data),0);
}

int ServerSocket::GetNbClients()
{
	return nbClients;
}

/*
not implemented yet
*/
bool ServerSocket::KillClient(int clientIp)
{
	return true;
}

/*
not implemented yet
*/
bool ServerSocket::KillClient(char * hostname)
{
	return true;
}

void ServerSocket::AddClientToVector(SOCKET s)
{
	clients.push_back(s);
}

void ServerSocket::RemoveClientToVector(SOCKET s)
{
	vector<SOCKET>::iterator iter;
	for( iter = clients.begin(); iter != clients.end(); ++iter ) 
	{
		if((*iter) == s)
		{
			clients.erase(iter);
			break;
		}
	}
}

vector<SOCKET>& ServerSocket::GetClients(void)
{
	return clients;
}
